package dataTypes;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 
 * @author Felix Schliephacke
 * 
 */
public final class FieldImpl implements Field<Integer> {

	public static Field<Integer> getInstance(final Field<Integer> field) {
		return new FieldImpl(field);
	}

	public static Field<Integer> getInstance(final int squareSize)
			throws IllegalArgumentException {
		if (squareSize <= 0) {
			throw new IllegalArgumentException(
					"Argument must be greater than 0.");
		}
		return new FieldImpl(squareSize);
	}

	public static Field<Integer> getInstance(final int squareSize,
			final Integer arg) {
		return new FieldImpl(squareSize, arg);
	}

	private transient final List<Integer> field;

	private transient final int size;

	private transient final int squareSize;

	private FieldImpl(final Field<Integer> field) {
		this.squareSize = field.getSquareSize();
		this.size = this.squareSize * this.squareSize;
		this.field = this.initList();
		for (final Integer temp : field) {
			this.field.add(temp);
		}
	}

	private FieldImpl(final int size) {
		this.squareSize = size;
		this.size = this.squareSize * this.squareSize;
		this.field = this.initList();
		this.reset();
	}

	private FieldImpl(final int squareSize, final Integer arg) {
		this.squareSize = squareSize;
		this.size = this.squareSize * this.squareSize;
		this.field = this.initList();
		if (arg == null) {
			this.reset();
		} else {
			this.field.add(arg);
		}
	}

	@Override
	public Field<Integer> clone() {
		return FieldImpl.getInstance(this);
	}

	@Override
	public boolean contains(final Integer arg) {
		return this.field.contains(arg);
	}

	@Override
	public boolean equals(final Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof FieldImpl)) {
			return false;
		}
		final FieldImpl other = (FieldImpl) obj;
		if (this.field == null) {
			if (other.field != null) {
				return false;
			}
		} else if (!this.field.equals(other.field)) {
			return false;
		}
		if (this.size != other.size) {
			return false;
		}
		return true;
	}

	@Override
	public Integer get(final int index) {
		return this.field.get(index);
	}

	@Override
	public int getSquareSize() {
		return this.squareSize;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ (this.field == null ? 0 : this.field.hashCode());
		result = prime * result + this.size;
		return result;
	}

	private List<Integer> initList() {
		return new ArrayList<Integer>(this.size);
	}

	@Override
	public Iterator<Integer> iterator() {
		return this.field.iterator();
	}

	@Override
	public boolean remove(final Integer arg) {
		return this.field.remove(arg);
	}

	@Override
	public void reset() {
		this.field.clear();
		for (int i = 1; i <= this.size; i++) {
			this.field.add(i);
		}
	}

	@Override
	public void set(final Integer content) {
		this.field.clear();
		this.field.add(content);
	}

	@Override
	public int size() {
		return this.field.size();
	}

	@Override
	public String toString() {
		return this.field.toString();
	}

	// @Override
	// protected void finalize() {
	// this.field = null;
	// }
}
